//
// Created by jsjxsy on 2024/7/31.
//
#include <stdio.h>
#include <libavutil/log.h>
#include <stdlib.h>
#include <libavformat//avformat.h>
int main(int argc, char *argv[]) {
  char *src;
  char *dist;
  AVFormatContext *pFmtCtx = NULL;
  AVFormatContext *oFmtCtx = NULL;
  AVOutputFormat *outFmt = NULL;
  AVStream *outStream = NULL;
  AVStream *inStream = NULL;
  AVPacket pkt;
  int ret = -1;
  int index = -1;

  av_log_set_level(AV_LOG_DEBUG);
  if (argc < 3) {
    av_log(NULL, AV_LOG_INFO, "arguments must be more than 3\n");
    exit(-1);
  }
  src = argv[1];
  dist = argv[2];

  ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);
  if (ret < 0) {
    av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));
    exit(-1);
  }

  index = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
  if (index < 0) {
    av_log(pFmtCtx, AV_LOG_ERROR, "does not include audio stream \n");
    goto _ERROR;
  }
  oFmtCtx = avformat_alloc_context();
  if (!oFmtCtx) {
    av_log(NULL, AV_LOG_ERROR, "No Memory!");
    goto _ERROR;
  }
  outFmt = av_guess_format(NULL, dist, NULL);
  oFmtCtx->oformat = outFmt;
  outStream = avformat_new_stream(oFmtCtx, NULL);
  inStream = pFmtCtx->streams[index];
  avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);
  outStream->codecpar->codec_tag = 0;
  ret = avio_open2(&oFmtCtx->pb, dist, AVIO_FLAG_WRITE, NULL, NULL);
  if (ret < 0) {
    av_log(oFmtCtx, AV_LOG_ERROR, "%s", av_err2str(ret));
    goto _ERROR;
  }
  ret = avformat_write_header(oFmtCtx, NULL);
  if (ret < 0) {
    av_log(oFmtCtx, AV_LOG_ERROR, "%s", av_err2str(ret));
    goto _ERROR;
  }
  while (av_read_frame(pFmtCtx, &pkt) >= 0) {
    if (pkt.stream_index == index) {
      //pts
      pkt.pts = av_rescale_q_rnd(pkt.pts,
                                  inStream->time_base,
                                  outStream->time_base,
                                  (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
      //dts
      pkt.dts = pkt.pts;
      pkt.duration = av_rescale_q(pkt.duration, inStream->time_base, outStream->time_base);
      pkt.stream_index = 0;
      pkt.pos = -1;
      av_interleaved_write_frame(oFmtCtx, &pkt);
      av_packet_unref(&pkt);
    }
  }
  av_write_trailer(oFmtCtx);
  _ERROR:
  if (pFmtCtx) {
    avformat_close_input(&pFmtCtx);
    pFmtCtx = NULL;
  }

  if (oFmtCtx->pb) {
    avio_close(oFmtCtx->pb);
  }

  if (oFmtCtx) {
    avformat_free_context(oFmtCtx);
    oFmtCtx = NULL;
  }
  return 0;
}